home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / pmode / pmode251 / pmode.doc < prev    next >
Text File  |  1994-11-29  |  31KB  |  656 lines

  1.  
  2.   Greetings... This is the documentation for PMODE v2.51 assembly protected
  3. mode header by Tran (a.k.a. Thomas Pytel). It is intended for assembly
  4. programmers with a good deal of knowlege of the 386. In this doc is explained
  5. the workings and usage of PMODE.ASM. This doc was originally written for a
  6. much earlier version of PMODE, but it is suitable (with minor adjustments) for
  7. PMODE v2.51.
  8.  
  9. ------------------------------------------------------------------------------
  10. Contents:
  11. ---------
  12.  
  13.   0 - Overview
  14.       0.0 - What it does
  15.       0.1 - Your code
  16.   1 - Memory, segments, and selectors
  17.       1.0 - Memory structure
  18.       1.1 - Usage and DOS
  19.       1.2 - Selectors
  20.   2 - The stack and calling across modes
  21.       2.0 - The stack
  22.       2.1 - Calling real mode
  23.       2.2 - Calling protected mode
  24.   3 - IRQs and exceptions
  25.       3.0 - IRQs
  26.       3.1 - DPMI and the stack
  27.       3.2 - Chaining to real mode
  28.       3.3 - The IF flag
  29.       3.4 - Exceptions
  30.   4 - Functions and data
  31.       4.0 - Variables
  32.       4.1 - Memory functions
  33.       4.2 - IRQ functions
  34.       4.3 - Selector functions
  35.       4.4 - Other functions
  36.   5 - Notes
  37.       5.0 - Updates
  38.       5.1 - DMA problems
  39.       5.2 - Misc notes
  40.       5.3 - Final word
  41.  
  42. ------------------------------------------------------------------------------
  43. 0 - Overview:
  44. -------------
  45.  
  46.   PMODE.ASM is a small piece of assembly code which is intended to allow for
  47. easy 32bit flat protected mode coding in assembly. I wrote it for myself, and
  48. it was designed for exactly what I need. But since it is so useful, and there
  49. are not too many other alternatives for protected mode ASM coding, I am
  50. putting it out for public distribution. The current version of PMODE has
  51. been evolving for a while. There has been plenty of time to refine and debug
  52. it. It is at this point, from my own and friends experiences, totally stable
  53. and bug-free. I do not make this statement lightly. But I do not guarantee it
  54. either.
  55.  
  56.   PMODE v2.51 is a touched up version of PMODE v2.4. Most (I think all) of the
  57. dead code has been removed from previous versions of PMODE. One minor DPMI bug
  58. has been fixed and the DPMI memory block allocation had been changed to
  59. compensate for a QDPMI bug (QEMM DPMI host). The previous allocation scheme
  60. may also have been the cause of memory allocation failure under OS/2. PMODE is
  61. a dedicated ASM extender. So far it has proven very stable and pretty clean
  62. over all. If you have been looking for something like this, feel free to use
  63. it. Or examine the source code if you just want to learn (though the code is a
  64. bit messy). All I ask if you use this code is credits.
  65.  
  66. 0.0 - What it does:
  67. -------------------
  68.  
  69.   PMODE provides a flat 32bit protected mode environment for assembly code to
  70. run in. No matter what kind of 386 protection control is already in place. It
  71. will run under VCPI, DPMI, or in raw mode with no 386 control system in place.
  72. This includes all the popular memory managers, Windows the virus, OS/2, etc...
  73. PMODE will take care of detecting a 386+ processor, making sure there is
  74. enough memory and allocating it. It will handle all the minor details of 386
  75. protected mode. Send IRQs that occur in protected mode to their real mode
  76. handlers, or allow you to intercept them. And, ofcourse, allow your protected
  77. mode code to call real mode interrupts and routines. PMODE will also take care
  78. of allocating and maintaining the stack across mode calls.
  79.  
  80.   When a PMODE program starts up, PMODE will do all of its necessary starup
  81. tasks. Then, if no error was detected (not enough mem, no 386+, etc...), it
  82. will jump to a label in your code called _main. Your program takes over from
  83. there with all interrupts disabled since real mode. You must do a STI to
  84. enable them. Don't forget this like I have so many times. When your program is
  85. done and wants to exit to DOS, simply jump to a label called _exit, defined
  86. in PMODE. You can pass back an error code to DOS. There is a variable called
  87. _exitcode which contains the byte to pass back to DOS (AL in INT 21h AH=4c).
  88.  
  89. 0.1 - Your code:
  90. ----------------
  91.  
  92.   All your 32bit code goes into one large CODE32 segment. It runs in 32bit
  93. protected mode from start to finish. All your code and data reside in this
  94. one large segment. Though you can read or write stuff below the beginning of
  95. CODE32. Within your code you will hardly ever have to worry about segment
  96. overrides or stuff like that. Its just pretty much straight flat assembly with
  97. full 32bit linear addresses for all your code and data. You can do most of the
  98. stuff you do in real mode. I would not suggest trying to go TSR or running
  99. external programs from your PMODE code though. It is doable, and will probably
  100. work, but PMODE was not designed for that. You would have to free up low
  101. memory yourself, and you can't free up high memory. There may be other minor
  102. problems uncompensated for. PMODE is meant for standalone ASM programs like
  103. games or demos, and does very well for that.
  104.  
  105. ------------------------------------------------------------------------------
  106. 1 - Memory, segments, and selectors:
  107. ------------------------------------
  108.  
  109.   In protected mode, your program has access to all free low and high memory
  110. that could be allocated. Low memory is all memory visible to DOS below 1M.
  111. High memory is all extended memory that could be allocated through VCPI, DPMI,
  112. XMS, or INT 15 AH=88h of raw mode. All this memory can be accessed directly
  113. realative to the beginning of the 32bit protected mode segment (CODE32). You
  114. can also access memory realative to the absolute beginning of memory. Three
  115. main selectors are set up by PMODE. One for the code segment starting at
  116. CODE32, its limit is set to 4G. One for a data segment alias for the code
  117. segment (same memory space), also at 4G. And one for a data segment beginning
  118. at the absolute beginning of memory. In fact, all selectors allocated by PMODE
  119. are set to a limit of 4G.
  120.  
  121. 1.0 - Memory structure:
  122. -----------------------
  123.  
  124.   The structure of memory when your code begins executing is as follows:
  125.  
  126. +-------------------------------------------------------------+
  127. | Normal crap (real mode int vector table, DOS, TSRs, etc...) |
  128. +-------------------------------------------------------------+
  129. | PSP                                                         |
  130. +-------------------------------------------------------------+
  131. | Beginning of CODE16 - PMODE 16bit code and data             |
  132. +-------------------------------------------------------------+
  133. | Beginning of CODE32 - PMODE 32bit code and data             |
  134. +-------------------------------------------------------------+
  135. | Your 32bit code and data                                    |
  136. +-------------------------------------------------------------+
  137. | The stack                                                   |
  138. +-------------------------------------------------------------+
  139. | PMODE data allocated at run-time (IDT, TSS, etc...)         |
  140. +-------------------------------------------------------------+
  141. | Free low memory (_lomembase to _lomemtop)                   |
  142. +-------------------------------------------------------------+
  143. | Video buffer, ROMS, also possibly hiram                     |
  144. +-------------------------------------------------------------+
  145. | Used extended memory (if any)                               |
  146. +-------------------------------------------------------------+
  147. | Free extended memory (if any, _himembase to _himemtop)      |
  148. +-------------------------------------------------------------+
  149. | Used extended memory (if any)                               |
  150. +-------------------------------------------------------------+
  151.  
  152.   When your code begins execution at _main, you can be sure there is a minimum
  153. of low memory available. This number is specified at the top of PMODE.ASM as
  154. LOWMIN. There is also a minimum of high memory specified in PMODE.ASM as
  155. EXTMIN. The beginning and ending addresses of these memory spaces, realative
  156. to the beginning of CODE32, are defined in four variables made available to
  157. your code. _lomembase is the linear address of the beginning of free low
  158. memory. _lomemtop is the linear address of the top of low memory (last
  159. possible byte+1). _himembase is the beginning of extended memory, and
  160. _himemtop is the end of it. All of these vars can be modified by your program.
  161. They will also be modified by PMODE memory functions. See section 4 for a
  162. description of these functions. Basically all that they do is see if there is
  163. enough memory available for a block you request. If there is, they pass back
  164. a pointer to the base of free memory of the type you requested, then adjust
  165. that base by the amount you requested.
  166.  
  167.   The functions (just tiny stubs of code really) provided for memory are just
  168. straight linear functions. No management of blocks of memory is done. I
  169. personally don't like fragmentations of memory, and can work fine without the
  170. need for blocks. If you want, write yourself a little malloc library if that
  171. is what you need.
  172.  
  173. 1.1 - Usage and DOS:
  174. --------------------
  175.  
  176.   When you call real mode DOS interrupts, or any real mode procedure that
  177. expects a buffer, you will have to make sure that buffer is in low memory.
  178. Remember that real mode DOS and code can only see low memory. Your code and
  179. data and the stack always reside in low memory. If you want to pass something
  180. that is in high memory however, you will have to copy it to somewhere in low
  181. memory. Once in low memory, you will have to get the real mode segment:offset
  182. pair for your linear address. Figuring this out is very easy. All linear
  183. addresses in PMODE are realative to the beginning of the CODE32 segment. To
  184. convert to an absolute address, all you have to do is add the offset of the
  185. CODE32 segment from absolute 0. And just this value is available in a variable
  186. called _code32a. All this really is, is the real mode segment value of CODE32
  187. shifted left 4 bits. So for example, _lomembase+_code32a is the linear address
  188. of the beginning of free low memory from absolute 0. And if you don't know how
  189. to convert this type of address to a seg:off pair, you should probably not be
  190. reading this doc just yet.
  191.  
  192. 1.2 - Selectors:
  193. ----------------
  194.  
  195.   As you know (and if you don't, get some books and learn more about protected
  196. mode), in protected mode the segment registers don't work with segment
  197. addresses, but with selectors. Selectors are indexes into tables describing
  198. segments. Appropriately enough these tables are called descriptor tables. And
  199. you do not have to worry about them, PMODE takes care of all the crap
  200. associated with them.
  201.  
  202.   The three main selectors you need (the code, data, and zero selectors) are
  203. set up by PMODE. Their numerical values are stored in three variables made
  204. available to your program. _selcode, _seldata, and _selzero are these
  205. variables. When your program begins execution at _main, CS is obviously set
  206. to _selcode, DS, ES, FS, and SS to _seldata, and GS is set to _selzero. With
  207. the exception of FS and SS, this is the state PMODE expects the segment regs
  208. to be whenever you call one of its functions or interrupts.
  209.  
  210.   PMODE also allows you to allocate extra data selectors and to set their base
  211. addresses to anything you want. This could be useful for tight routines where
  212. you want to conserve register space and use 16bit register addressing. You
  213. can specify the maximum number of selectors you will need to have allocated
  214. at any one time at the top of PMODE.ASM in the SELECTORS equate.
  215.  
  216.   During the execution of your code, you can modify DS, ES, FS, and GS to
  217. whatever selector you wish. Just remember to set the appropriate values for
  218. DS, ES, and GS before calling and PMODE functions or interrupts. Throughout
  219. the execution of your program you can assume SS to be _seldata. Except in the
  220. special case of IRQ handlers, explained in section 3.
  221.  
  222. ------------------------------------------------------------------------------
  223. 2 - The stack and calling across modes:
  224. ---------------------------------------
  225.  
  226.   The stack and calling across modes are closely tied together. Multiple
  227. nested calls from protected to real mode and back are supported. DPMI also
  228. feels the need to complicate the situation a little in dealing with IRQs, but
  229. more on that later. You do not have to worry about the stack in calling across
  230. modes, PMODE will take care of it.
  231.  
  232. 2.0 - The stack:
  233. ----------------
  234.  
  235.   PMODE sets up and maintains the stack for your program. In fact, your code
  236. should not attempt to set up its own stack. Both because its not necessary,
  237. and because of some other stupid historical reasons that I have forgotten by
  238. now. There are four equates at the top of PMODE.ASM that determine the final
  239. size and allocation of the stack. STAKMAIN sets the size of your main program
  240. stack. The stack that will be used in your main stream of execution. STAKRMODE
  241. is the size of the stack that will be given to any real mode code that is
  242. called from protected mode. STAKPMODE is the size of the stack given to any
  243. protected mode routines called from real mode. MODENESTING is the maximum
  244. number of nested cross-mode calls supported. The final size of the master
  245. stack is determined from all of these variables, and it cannot exceed 64k.
  246.  
  247. 2.1 - Calling real mode:
  248. ------------------------
  249.  
  250.   From your protected mode code you can call real mode interrupts and routines
  251. using protected mode interrupts set up by PMODE for this purpose. You pass
  252. registers to the real mode interrupt or routine through the use of virtual
  253. registers, which are just memory images of the values to be set for those
  254. registers in real mode. There are virtual registers for EAX, EBX, ECX, EDX,
  255. ESI, EDI, EBP, DS, ES, FS, and GS. The virtual registers for AL, AH, and AX
  256. share the appropriate memory space within the virtual EAX reg. Notice that
  257. there are no SS, ESP, CS, and EIP registers. CS:EIP is taken from the real
  258. mode interrupt vektor table for interrupt calls, and passed in the real CX:DX
  259. registers for a procedure call. SS:ESP is set up by PMODE.
  260.  
  261.   An INT 32h instruction in protected mode calls a real mode procedure. The
  262. real CX:DX registers are the seg:off of the real mode procedure. The real mode
  263. procedure must return with a RETF. The interrupt enable flag is preserved
  264. across the call to real mode, but not back. After the INT 32h the IF flag will
  265. be the same as before. The real carry, zero, aux, parity, sign, and overflow
  266. flags will be passed back from the real mode routine unchanged. The real CPU
  267. registers will be set to the values of the virtual registers for the real mode
  268. routine. The return values of the routine will be stored back into the virtual
  269. registers. The actual CPU registers will be unchanged in protected mode.
  270.  
  271.   An INT 33h in protected mode will call a real mode interrupt handler. AL is
  272. the interrupt number you want to call. The interrupt flag is disabled for the
  273. real mode interrupt handler just as it is in real mode. Other than this, INT
  274. 33h works just like INT 32h with respect to virtual registers and the real
  275. flags passed back from the handler.
  276.  
  277.   One minor thing I must point out. INT 32h and INT 33h do not preserve FS. It
  278. is returned as _seldata.
  279.  
  280. 2.2 - Calling protected mode:
  281. -----------------------------
  282.  
  283.   You can also call a protected mode routine from real mode. The virtual
  284. registers are used again to pass register values. With the exception of the
  285. segment registers. For the protected mode routine, CS will obviously be
  286. _selcode. DS, ES, FS, and SS will be _seldata. GS will be _selzero. Also, the
  287. direction flag will be cleared for the protected mode routine. The virtual
  288. DS, ES, FS, and GS registers are untouched by a call to a protected mode
  289. routine. The interrupt enable flag is preserved across the call, but not back,
  290. just like a protected mode call to INT 32h. The carry, zero, aux, parity,
  291. sign, and overflow flags are also passed back real mode from the protected
  292. mode routine. To call a protected mode routine from real mode, do an INT 32h
  293. in real mode. That's right, another INT 32h. But its a different handler from
  294. the protected mode version of the int. The offset of the protected mode
  295. routine you want to call should be in EDX. And that routine must return with
  296. a regular RET.
  297.  
  298. ------------------------------------------------------------------------------
  299. 3 - IRQs and exceptions:
  300. ------------------------
  301.  
  302.   First thing, let me just say that many DPMI drivers are very buggy in the
  303. area of IRQs. They may not reflect them properly to real mode. Or they may
  304. screw up if you try to do a call to real mode from a protected mode IRQ
  305. handler. Keep this is mind if you are testing your code under a DPMI system.
  306.  
  307. 3.0 - IRQs:
  308. -----------
  309.  
  310.   By default, IRQs that occur in protected mode are sent on to their real mode
  311. handlers (this counts as a mode switch to the PMODE master stack). PMODE
  312. allows you to install your own protected mode IRQ handlers. There are two
  313. functions for getting and setting protected mode IRQ vectors in PMODE (see
  314. section 4). Once set with these functions, your protected mode IRQ handler
  315. will be active, but only in protected mode. If an IRQ you have hooked occurs
  316. while processing a call to real mode (INT 32h or 33h or an IRQ that is being
  317. processed by its real mode handler), it will go to the handler specified in
  318. the real mode interrupt vector table. PMODE provides another set of functions
  319. to create real mode callbacks to protected mode IRQ handlers, so that your
  320. handler will get control no matter where the IRQ occurred. These callbacks,
  321. however, modify the real mode interrupt vector table. Making chaining to the
  322. real mode handler not as easy as using INT 33h with the appropriate interrupt
  323. number.
  324.  
  325.   You should terminate any protected mode IRQs with an IRETD (notice the D).
  326. DPMI dox also say that this may not restore the interrupt enable flag, so
  327. you should do a STI just before. However, all DPMIs I have tested seem to
  328. restore the flag correctly without the STI.
  329.  
  330. 3.1 - DPMI, and the stack:
  331. --------------------------
  332.  
  333.   The one anomaly to PMODEs stack with IRQs is DPMI. It sees fit to switch
  334. onto its own stack whenever an IRQ goes off. And if you try to switch off that
  335. stack, you will be severely punished by DPMI. For this reason, calls to real
  336. mode (INT 32h, 33h) from IRQs under DPMI may or may not work depending on what
  337. DPMI you're running under and how buggy it is. I have had no problems with
  338. Windows DPMI driver in these situations, but you have been warned. Because
  339. DPMI switches onto its own stack, you can not assume anything about SS in IRQ
  340. handlers, and should definately not mess with it.
  341.  
  342. 3.2 - Chaining to real mode:
  343. ----------------------------
  344.  
  345.   If you don't set the real mode IRQ callback for a particular IRQ, chaining
  346. to that IRQs real mode handler is as easy as using INT 33h with the
  347. appropriate interrupt number. But you probably will set the callbacks. In
  348. which case, if you use INT 33h, it will just go to the protected mode IRQ
  349. handler. And if this INT 33h call was from the protected mode IRQ handler,
  350. well, lets just say infinite loop. If you have the callback set, and you wish
  351. to chain (why bother?), you must make the address of the real mode IRQ handler
  352. available to a real mode far routine that will call that handler as an
  353. interrupt routine. You should call this real mode routine with INT 32h from
  354. protected mode to do the IRQ chaining.
  355.  
  356. 3.3 - The IF flag:
  357. ------------------
  358.  
  359.   DPMI may need to virtualize the real system interrupt flag in protected
  360. mode. For this reason you may not assume anything about the IF flag and
  361. instructions which usually modify it. For example, PUSHF(D) may not store the
  362. actual IF flag on the stack, and POPF(D) may not change either the real IF
  363. flag or the virtual one. You can however be sure that CLI and STI will carry
  364. out their functions correctly. Also, PMODE will replicate DPMIs native
  365. interrupt flag functions if DPMI is not present. They are on INT 31h in
  366. protected mode and are as follows:
  367.  
  368.   AX=900h: Get state of IF then disable it. Returns AL set to the IF flag.
  369.   AX=901h: Get state of IF then enable it. Returns AL set to the IF flag.
  370.   AX=902h: Only returns AL set to the IF flag (0=disabled, 1=enabled).
  371.  
  372. 3.4 - Exceptions:
  373. -----------------
  374.  
  375.   Under DPMI, exceptions are handled by the DPMI driver, which will usually
  376. just terminate your program. Otherwise PMODE will automatically exit to DOS
  377. on any exception not overridden by the low 8 IRQs. Any exception that is, will
  378. erroneously be sent to that IRQ handler, be it a protected mode handler or
  379. a real mode handler. Hey, you should not be getting exceptions in the first
  380. place.
  381.  
  382. ------------------------------------------------------------------------------
  383. 4 - Functions and data:
  384. -----------------------
  385.  
  386.   PMODE makes some variables available to your program concerning the state of
  387. the system and memory. It also provides some functions for dealing with IRQs,
  388. memory, and selectors. These functions and vars are defined in PMODE.INC. Just
  389. include that somewhere in your code. Some of the functions are actually
  390. defined as dwords, not as near lables. This is because their address may be
  391. modified at startup to point to appropriate functions for the system type.
  392. Don't worry about this. Just call them as you would call normal functions. So
  393. here is a summary of all data and functions you can use. The functions
  394. definitions are pretty self-explanatory. Except maybe that CF=0 means carry
  395. flag clear, and CF=1 means a cheeseburger, hold the mayo.
  396.  
  397. 4.0 - Variables:
  398. ----------------
  399.  
  400. _selcode:word - The 32bit code selector.
  401.  
  402. _seldata:word - The 32bit data selector (alias for the code).
  403.  
  404. _selzero:word - The 32bit data selector starting at absolute 0.
  405.  
  406. _lomembase:dword - The linear address of the current base of low memory.
  407.  
  408. _lomemtop:dword - The linear address of the current top of low memory.
  409.  
  410. _himembase:dword - The linear address of the current base of high memory.
  411.  
  412. _himemtop:dword - The linear address of the current top of high memory.
  413.  
  414. _pspa:dword - The linear address of the PSP from absolute 0.
  415.  
  416. _code16a:dword - The linear address of the CODE16 segment from absolute 0.
  417.  
  418. _code32a:dword - The linear address of the CODE32 segment from absolute 0.
  419.  
  420. _sysbyte0:byte - The low 2 bits are the system type, 0=raw, 1=XMS, 2=VCPI,
  421.   3=DPMI. The high 6 bits are undefined.
  422.  
  423. _exitcode:byte - The exit code you want to pass to DOS, 0 by default.
  424.  
  425. Here are the virtual registers for cross-mode calls:
  426.  
  427.   v86r_eax:dword, v86r_ebx:dword, v86r_ecx:dword, v86r_edx:dword
  428.   v86r_esi:dword, v86r_edi:dword, v86r_ebp:dword
  429.   v86r_ah:byte, v86r_al:byte, v86r_bh:byte, v86r_bl:byte
  430.   v86r_ch:byte, v86r_cl:byte, v86r_dh:byte, v86r_dl:byte
  431.   v86r_ax:word, v86r_bx:word, v86r_cx:word, v86r_dx:word
  432.   v86r_si:word, v86r_di:word, v86r_bp:word
  433.   v86r_ds:word, v86r_es:word, v86r_fs:word, v86r_gs:word
  434.  
  435. 4.1 - Memory functions:
  436. -----------------------
  437.  
  438. _getlomem - Allocate some low mem
  439.   In:
  440.     EAX - size requested
  441.   Out:
  442.     CF=0 - memory allocated
  443.     CF=1 - not enough mem
  444.     EAX - linear pointer to mem or ?
  445.  
  446. _gethimem - Allocate some high mem
  447.   In:
  448.     EAX - size requested
  449.   Out:
  450.     CF=0 - memory allocated
  451.     CF=1 - not enough mem
  452.     EAX - linear pointer to mem or ?
  453.  
  454. _getmem - Allocate any mem, (first cheks low, then high)
  455.   In:
  456.     EAX - size requested
  457.   Out:
  458.     CF=0 - memory allocated
  459.     CF=1 - not enough mem
  460.     EAX - linear pointer to mem or ?
  461.  
  462. _lomemsize - Get amount of free low mem
  463.   Out:
  464.     EAX - number of bytes free
  465.  
  466. _himemsize - Get amount of free high mem
  467.   Out:
  468.     EAX - number of bytes free
  469.  
  470. 4.2 - IRQ functions:
  471. --------------------
  472.  
  473. _getirqvect - Get protected mode IRQ handler offset
  474.   In:
  475.     BL - IRQ num (0-0fh)
  476.   Out:
  477.     EDX - offset of IRQ handler
  478.  
  479. _setirqvect - Set protected mode IRQ handler offset
  480.   In:
  481.     BL - IRQ num (0-0fh)
  482.     EDX - offset of IRQ handler
  483.  
  484. _getirqmask - Get status of IRQ mask bit
  485.   In:
  486.     BL - IRQ num (0-15)
  487.   Out:
  488.     AL - status: 0=enabled, 1=disabled
  489.  
  490. _setirqmask - Set status of IRQ mask bit
  491.   In:
  492.     BL - IRQ num (0-15)
  493.     AL - status: 0=enabled, 1=disabled
  494.  
  495. _rmpmirqset - Set a real mode IRQ vect to redirect to pmode
  496.   In:
  497.     BL - IRQ number
  498.     EDX - offset of IRQ handler
  499.     EDI -> 21 byte buffer for code stub created
  500.   Out:
  501.     EAX - old seg:off of real mode IRQ handler
  502.  
  503. _rmpmirqfree - Reset a real more IRQ vect back to normal
  504.   In:
  505.     BL - IRQ number
  506.     EAX - seg:off of real mode IRQ handler
  507.  
  508. 4.3 - Selector functions:
  509. -------------------------
  510.  
  511. _getselector - Allocate a selector
  512.   Out:
  513.     CF=1 - selector not allocated
  514.     CF=0 - selector allocated
  515.     AX - 4G data selector or ?
  516.  
  517. _freeselector - Free an allocated selector
  518.   In:
  519.     AX - selector
  520.  
  521. _setselector - Set the base addx for a selector
  522.   In:
  523.     AX - selector
  524.     EDX - linear base addx for selector
  525.  
  526. 4.4 - Other functions:
  527. ----------------------
  528.  
  529. _exit - Exit to real mode
  530.  
  531. _ret - Absolutely nothing, just a RET instruction
  532.  
  533. ------------------------------------------------------------------------------
  534. 5 - Notes:
  535. ----------
  536.  
  537.   In this section is a whole bunch of info that didn't really fit into the
  538. other sections, or that I want to emphasize. If you run into a weird bug,
  539. check here to for some possibilities. It is easy to forget enable interrupts
  540. when your program gains control. Or to forget theres a limit to the stack
  541. since control of it is taken away from your program.
  542.  
  543. 5.0 - Updates (since 2.5):
  544. --------------------------
  545.  
  546. PMODE 2.51:
  547. ) Added control of the order of DPMI/VCPI detection.
  548.  
  549. ) Added compensation for EMM386 screwing the high bits of ESP in real mode.
  550.  
  551. 5.1 - DMA Problems:
  552. -------------------
  553.  
  554.   As you know, the DMA controllers in the PC use all physical addresses.
  555. Nothing but the processor itself knows how linear memory is arranged in the
  556. physical memory banks. When paging is disabled, the relationship is very
  557. simple. The linear address is always the same as the physical address. But
  558. when you enable paging, that could get all screwed up. In raw mode and XMS,
  559. you don't have to worry about this since paging is disabled. But under VCPI
  560. and DPMI things are different. You can almost definately count on extended
  561. memory addresses not being consistent with their physical addresses. Low
  562. memory however, will usually map perfectly to its physical addresses. Unless
  563. the program is running in some sort of multitasking system. Then the chances
  564. are slim. The point is that you can't trust DMA much under VCPI and DPMI.
  565.  
  566.   Ive seen the specs for VDS, and its useless for the type of DMA I need to
  567. do. So there is no support for it in PMODE. If you feel like it, use it
  568. yourself if you detect it.
  569.  
  570. 5.2 - Misc notes:
  571. -----------------
  572.  
  573. ) No, you can't link PMODE with any high level languages.
  574.  
  575. ) When linking, PMODE must be the first object in the link list.
  576.  
  577. ) PMODE functions and INTs expect the direction flag to be clear.
  578.  
  579. ) In IRQ handlers, you should not assume anything about the stack.
  580.  
  581. ) Under VCPI, PMODE will allocate a maximum of 60M extended memory.
  582.  
  583. ) You do not have to free any selectors you allocate before exiting.
  584.  
  585. ) Remember to use 'IRETD' not 'IRET' at the end of protected mode IRQs.
  586.  
  587. ) I would REALLY suggest not ever switching your stack in protected mode
  588. yourself.
  589.  
  590. ) Remember that upon reaching '_main', interrupts are still disabled. Don't
  591. forget to do the STI.
  592.  
  593. ) You can't write to memory with a CS: override in protected mode, but you can
  594. read with a CS: override.
  595.  
  596. ) This thing was tested under TASM 4.0. So if you have something different,
  597. don't blame me if it doesnt compile.
  598.  
  599. ) Yeah, theres no debugger. Quit whining, don't you realize it runs under
  600. DPMI? So you can use any old DPMI debugger.
  601.  
  602. ) When doing multiple nested cross-mode calls, keep in mind that the same
  603. virtual regs are used to pass register values.
  604.  
  605. ) Division faults, single step interrupts, the NMI, INT3, INTO, and BOUND
  606. faults are sent to real mode handlers for the appropriate int number.
  607.  
  608. ) If you modify the base address of a selector you allocated, make sure to
  609. reload any segment registers containing that selector before using them.
  610.  
  611. ) I hope you realize that in PMODE IRQ handlers, you don't have the BIOS to
  612. redirect IRQ9 to IRQ2. So any device that uses IRQ2 will actually be using 9.
  613.  
  614. ) If you're getting problems that smell of stack trouble, try increasing the
  615. stack size vars at the top of PMODE.ASM and the maximum nesting level if
  616. you're doing many calls across modes.
  617.  
  618. ) Upon entry to a protected mode IRQ handler, remember that all segregs are
  619. in an unknown state, including DS. Don't forget the 'mov ds,cs:_seldata'. Also
  620. ofcourse preserve the previous value of all the regs.
  621.  
  622. ) Remember that the INT31 AX=9?? flag functions are only available in pmode.
  623. Go ahead, use the PUSHFs and POPFs in real mode to alter the IF flag... And
  624. any DPMI host that can't handle that properly deserves to crash.
  625.  
  626. ) There may be weird problems under some DPMIs. Many DPMI drivers out there
  627. are anywhere from a little to extremely buggy. If you suspect your DPMI
  628. driver, try running without it, or under a different DPMI driver.
  629.  
  630. ) If you're gonna add other segments, put them between CODE16 and CODE32 only
  631. if theyre small enough to still allow access to CODE32 data from CODE16.
  632. Otherwise put them between CODE32 and CODEEND. You can also just stick your
  633. 16bit code in the CODE16 segment.
  634.  
  635. ) Before exiting your program, you do not need to restore any protected mode
  636. IRQ vectors. If you modified the real mode vector table, you gotta restore
  637. those. And you do not have to restore the IRQ masks at 21h and A1h, PMODE
  638. stores them before jumping to _main, and restores them before exiting.
  639.  
  640. ) PMODE does not handle the VDISK low to high extended memory allocation
  641. scheme because it is just plain stupid (and does not seem to be used outside
  642. of XMS where its not a problem since the XMS driver is used to allocate mem).
  643. If you wanna take precautions for this type of allocation, make yourself a
  644. little macro to check for it and adjust _himembase accordingly.
  645.  
  646. 5.3 - Final word:
  647. -----------------
  648.  
  649.   Well thats that... If you have a problem with something in PMODE, code your
  650. own. Use this code, or don't, its your choice. Or just use it to learn if you
  651. wish. Oh well...
  652.  
  653.                                                 L8r...
  654.                                                 Tran...
  655.  
  656.